package com.siyoumi.app.modules.lucky_num.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.siyoumi.app.entity.*;
import com.siyoumi.app.modules.lucky_num.service.Impl.LNumSessionImplDef;
import com.siyoumi.app.modules.lucky_num.vo.LNumChouWinItem;
import com.siyoumi.app.modules.lucky_num.vo.LNumChouWin;
import com.siyoumi.app.modules.lucky_num.vo.VaLnumSession;
import com.siyoumi.app.service.LnumNumService;
import com.siyoumi.app.service.LnumSessionService;
import com.siyoumi.app.service.LnumWinService;
import com.siyoumi.component.XApp;
import com.siyoumi.component.http.InputData;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.mybatispuls.JoinWrapperPlus;
import com.siyoumi.service.IWebService;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

//奖品期
@Slf4j
public abstract class SvcLNumSession
        implements IWebService {
    static public SvcLNumSession getBean() {
        return new LNumSessionImplDef();
    }

    static public LnumSessionService getApp() {
        return LnumSessionService.getBean();
    }


    /**
     * select
     *
     * @return query
     */
    public JoinWrapperPlus<LnumSession> listQuery(InputData inputData) {
        String name = inputData.input("name");
        String groupId = inputData.input("group_id");

        JoinWrapperPlus<LnumSession> query = getApp().join();
        query.eq("lns_x_id", XHttpContext.getX())
                .eq("lns_del", 0);
        getApp().addQueryAcc(query);
        //排序
        query.orderByAsc("lns_order")
                .orderByDesc("lns_id");
        if (XStr.hasAnyText(name)) { //名称
            query.like("lns_name", name);
        }
        if (XStr.hasAnyText(groupId)) { //号码组
            query.eq("lns_group_id", groupId);
        }

        return query;
    }

    public XReturn edit(InputData inputData, VaLnumSession vo) {
        List<String> ignoreField = new ArrayList<>();
        if (inputData.isAdminEdit()) {
            ignoreField.add("lns_acc_id");
        }

        vo.setLnset_acc_id(vo.getLns_acc_id());

        LnumGroup entityGroup = SvcLNumGroup.getApp().first(vo.getLns_group_id());

        return XApp.getTransaction().execute(status -> {
            XReturn r = getApp().saveEntity(inputData, vo, true, ignoreField);
            LnumSession entity = r.getData("entity");

            List<String> groupTypeArr = List.of("fun_win", "sign_chou"); //积分夺宝,报名抽奖
            if (groupTypeArr.contains(entityGroup.getLngroup_type())) {
                //初始化，号码设置
                SvcLnumNumSet.getBean().editSave(entity.getKey(), vo);
            }

            return r;
        });
    }

    /**
     * 删除
     */
    @SneakyThrows
    public XReturn delete(List<String> ids) {
        XReturn r = XReturn.getR(0);

//        List<LnumSession> listSession = getApp().get(ids, XHttpContext.getX());
//        List<String> groupIds = listSession.stream().filter(item -> item.getLngroup_type() == 0).map(item -> item.getLngroup_id()).collect(Collectors.toList());
//        if (groupIds.size() > 0) {
//            //删除组，同时删除号码配置
//            SvcLnumNumSet.getBean().delete(groupIds);
//        }

        getApp().delete(ids);

        return r;
    }

    /**
     * 开奖
     *
     * @param vo
     */
    public XReturn chouWin(LNumChouWin vo) {
        LnumSession entitySession = SvcLNumSession.getApp().first(vo.getSession_id());
        if (entitySession.win()) {
            return XReturn.getR(20104, "已开奖");
        }
        if (entitySession.winLeftSeconds() > 0) {
            return XReturn.getR(20105, "未到开奖时间");
        }

        SvcLNumSessionPrize appPrize = SvcLNumSessionPrize.getBean();
        List<LnumSessionPrize> listPrize = appPrize.list(entitySession.getKey());
        if (listPrize.size() <= 0) {
            return XReturn.getR(20114, "奖品数量为0");
        }

        JoinWrapperPlus<LnumNum> numQuery = SvcLNumGroup.getBean().numQuery(entitySession.getLns_group_id(), InputData.getIns());
        numQuery.le("lnum_create_date", entitySession.getLns_win_date_end());
        JoinWrapperPlus<LnumNum> numQueryList = numQuery.cloneJoinPlus();

        Long numCount = LnumNumService.getBean().count(numQuery);
        if (numCount <= 0) {
            XReturn r = XReturn.getR(20124, "号码数量为0");
            r.setData("win_date_end", entitySession.getLns_win_date_end());
            r.setData("group_id", entitySession.getLns_group_id());
            return r;
        }
        long prizeTotal = listPrize.stream().mapToLong(LnumSessionPrize::getLnsp_count).sum();
        if (prizeTotal != vo.getItems().size()) {
            return XReturn.getR(20134
                    , XStr.concat("输入号码数量与奖品数量不相等," + vo.getItems().size(), "," + prizeTotal)
            );
        }

        log.debug("获取所有号码");
        List<Long> nums = vo.getItems().stream().map(LNumChouWinItem::getNum).collect(Collectors.toList());
        List<String> numErrArr = new ArrayList<>();
        for (Long num : nums.stream().distinct().collect(Collectors.toList())) {
            if (nums.stream().filter(item -> item.equals(num)).count() > 1) {
                //找出复制号码
                numErrArr.add(num.toString());
            }
        }

        if (numErrArr.size() > 0) {
            return XReturn.getR(20135, "开奖号码存在相同，" + numErrArr.stream().collect(Collectors.joining(",")));
        }

        numQueryList.in("lnum_num", nums);
        List<LnumNum> listNum = LnumNumService.getBean().get(numQueryList);

        Long rndNum = XDate.toS();
        log.debug("开始发奖");
        for (LNumChouWinItem num : vo.getItems()) {
            LnumNum entityNum = listNum.stream()
                    .filter(item -> item.getLnum_num().equals(num.getNum()))
                    .findFirst().orElse(null);
            if (entityNum == null) {
                XValidator.err(20135, num.getNum() + "：号码不存在");
            }
            LnumSessionPrize entityPrize = listPrize.stream()
                    .filter(item -> item.getLnsp_id().equals(num.getPrize_id()))
                    .findFirst().orElse(null);
            if (entityPrize == null) {
                XValidator.err(20136, num.getNum() + "：奖品ID不存在");
            }

            XReturn r = appPrize.sendPrize(entityNum.getLnum_num(), entityPrize, rndNum.intValue(), numCount.longValue());
            if (r.err()) {
                r.setErrMsg("开奖失败，", r.getErrMsg());
                XValidator.err(r);
            }

            rndNum++;
        }
        log.debug("标记奖品期已发奖");
        //控制只能开1次奖
        //Svc__t_c_system_key.getBean().add("lucky_num|chou", entitySession.getLnums_id());

        LnumSession entitySessionUpdate = new LnumSession();
        entitySessionUpdate.setLns_id(entitySession.getKey());
        entitySessionUpdate.setLns_win(1);
        entitySessionUpdate.setLns_win_date(LocalDateTime.now());
        SvcLNumSession.getApp().saveOrUpdatePassEqualField(entitySession, entitySessionUpdate);

        return EnumSys.OK.getR();
    }

    public XReturn list(InputData inputData) {
        SvcLNumSessionPrize appSessionPrize = SvcLNumSessionPrize.getBean();

        String groupId = inputData.input("group_id");
        String sessionId = inputData.input("session_id"); //奖品期

        String win = inputData.input("win");
        if (XStr.isNullOrEmpty(groupId)) {
            return EnumSys.MISS_VAL.getR("miss groupId");
        }

        Boolean showWin = false; //显示中奖详情
        if ("1".equals(win) && XStr.hasAnyText(sessionId)) {
            showWin = true;
        }

        LnumGroup entityGroup = SvcLNumGroup.getApp().first(groupId);
        if (entityGroup == null) {
            return EnumSys.ERR_VAL.getR("group_id异常");
        }
        boolean userWin = false; //用户是否中奖

        JoinWrapperPlus<LnumSession> query = listQuery(inputData);
        IPage<LnumSession> page = new Page<>(inputData.getPageIndex(), inputData.getPageSize(), false);
        //奖品期列表
        IPage<LnumSession> pageData = getApp().get(page, query);
        List<LnumSession> list = pageData.getRecords();
        //
        log.debug("获取所有奖品期的奖品");
        List<String> sessionIds = list.stream().map(LnumSession::getLns_id).collect(Collectors.toList());
        List<LnumSessionPrize> listPrize = appSessionPrize.list(sessionIds);
        //
        List<Map<String, Object>> listData = new ArrayList<>();
        for (LnumSession entitySession : list) {
            //获取对应奖品期-奖品
            List<LnumSessionPrize> listPrizeS = listPrize.stream()
                    .filter(item -> item.getLnsp_session_id().equals(entitySession.getKey()))
                    .collect(Collectors.toList());

            Map<String, Object> mapSession = entitySession.toMap();
            //离开奖还剩x秒
            mapSession.put("win_left_s", entitySession.winLeftSeconds());

            //奖品列表
            List<Map<String, Object>> listMapPrize = new ArrayList<>();
            for (LnumSessionPrize entityPrize : listPrizeS) {
                Map<String, Object> mapPrize = entityPrize.toMap();

                if (entitySession.win() && showWin) {
                    //已开奖，需要显示中奖号码
//                    List<Map<String, Object>> listWinS = listWin.stream().filter(item ->
//                    {
//                        return item.get("lwin_session_id").equals(entitySession.getLnums_id())
//                                && item.get("lwin_prize_id").equals(entityPrize.getLnsp_id());
//                    }).collect(Collectors.toList());
//                    mapPrize.put("list_win", listWinS);
                }

                listMapPrize.add(mapPrize);
            }
            mapSession.put("list_prize", listMapPrize);

            listData.add(mapSession);
        }

        XReturn r = XReturn.getR(0);
        r.setData("list_data", listData);
        r.setData("user_win", userWin);
//        r.setData("user_win_prize", userWinPrize);
        return r;
    }


    public List<Map<String, Object>> winList(String sessionId) {
        String[] select = {
                "lwin_id",
                "lwin_num",
                "lwin_wxuser_id",
                "lwin_wxuser_id__master",
                "lwin_session_id",
                "lwin_prize_id",
                "lwin_get_count",
                "lwin_prize_item_num",
                "lwin_wxuser_id__master",
                "lwin_invalid",
                "lwin_invalid__master",
                "lwin_again",
        };

        JoinWrapperPlus<LnumWin> query = winQuery(List.of(sessionId));
        query.select(select);
        //按奖品排序
        query.orderByAsc("lnsp_order")
                .orderByDesc("lnsp_create_date");

        return LnumWinService.getBean().getMaps(query);
    }

    /**
     * 中奖记录
     */
    public JoinWrapperPlus<LnumWin> winQuery(List<String> sessionIds) {

        JoinWrapperPlus<LnumWin> query = LnumWinService.getBean().join();
        query.join(LnumSessionPrize.table(), LnumSessionPrize.tableKey(), "lnwin_prize_id");

        query.in("lnwin_session_id", sessionIds)
                .eq("lnwin_x_id", XHttpContext.getX());

        return query;
    }
}
